// 函数的定义

function add1(x:number, y:number):number {
  return x + y
}

let add2: (x: number, y: number) => number 

type add3 = (x: number, y: number)  => number 

interface add4 {
  (x:number, y:number) : number
}

function add5(x:number, y?: number) {
  return y ? x + y : y
}

console.log(add5(4));

function add6(x:number, y = 0, z:number, q = 1) {
  console.log(x,y,z,q);  // 1 0 3 1 
  return x + y + z + q
}

console.log(add6(1,undefined,3));  // 

// function add7(x:number, reset:Array<number>) {
//   console.log(x, reset);
//   return x + reset.reduce((pre,cur) => pre + cur )
// }
// console.log(add7(1,[2,3,4,5,6,7]));
// or
function add7(x:number, ...reset:number[]) {
  return x + reset.reduce((pre,cur) => pre + cur) 
}

console.log(add7(1,2,3,4,5,6,7));

// 函数的重载
/**
 * 
 * @param reset 
 *  为了让编译器能够选择正确的检查类型，它与JavaScript里的处理流程相似。 它查找重载列表，尝试使用第一个重载定义。 如果匹配的话就使用这个。
 *  因此，在定义重载的时候，一定要把最精确的定义放在最前面。
    注意，function add8(...reset:any[])并不是重载列表的一部分，因此这里只有两个重载：一个是接收字符串另一个接收数字。 以其它参数调用 add8会产生错误
 */
function add8(...reset:number[]): number;
function add8(...reset:string[]): string;
function add8(...reset:any[]) {
  let first = reset[0]
  if (typeof first === 'number') {
    return reset.reduce((pre,cur) => pre + cur)
  }
  if (typeof first === 'string') {
    return reset.join('')
  }
}

console.log(add8(1,2,3));
console.log(add8('1','b','c'));


// 元组
// let tuple: [number,string, object] = [1, '222', {name: 'cc'}]  

// 函数
// let add = (x:number,y: any) => x + y
// let add = (x:number,y: any): number => x + y

// 对象

// let obj: { x:any, y: string } = {x: 1, y: ""}

// 枚举类型
